package org.freez4.spring.bean.definition;

import org.freez4.spring.bean.factory.DefaultUserFactory;
import org.freez4.spring.bean.factory.UserFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 特殊 Bean 实例化Demo
 * 方式一 : ServiceLoad
 * 1. JDK {@link ServiceLoader} 原生API 初始化Bean
 * 2. springframework 适配 {@link ServiceLoaderFactoryBean}
 * 方式二 : springframework API
 * 1. {@link AutowireCapableBeanFactory#createBean(Class)}
 * 2. {@link BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)}
 *
 * @author 阿坤同学
 * @date 2023/12/6 4:43 PM
 */
public class SpecialBeanInstantiationDemo {

    private static final Logger logger = Logger.getLogger(SpecialBeanInstantiationDemo.class.getName());

    public static void main(String[] args) {
        // JDK 原生ServiceLoad使用
        serviceLoadDemo();
        // springframework ServiceLoad 适配
        springframeworkServiceLoadAdapter();
        // AutowireCapableBeanFactory#createBean
        createBeanByAutowireCapableBeanFactory();
    }

    /**
     * java SPI 加载User Bean对象。
     *
     * @author 阿坤同学
     * @date 2023/12/6 4:46 PM
     */
    public static void serviceLoadDemo() {
        ServiceLoader<UserFactory> serviceLoader = ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());
        displayServiceLoad(serviceLoader);
    }

    /**
     * springframework ServiceLoad 适配。
     *
     * @author 阿坤同学
     * @date 2023/12/6 4:49 PM
     */
    public static void springframeworkServiceLoadAdapter() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/special-bean-instantiation-context.xml");
        ServiceLoader<UserFactory> userFactoryServiceLoader = applicationContext.getBean("userFactoryServiceLoader", ServiceLoader.class);
        displayServiceLoad(userFactoryServiceLoader);
    }

    /**
     * 通过springframework Bean Factory API 创建用户对象。
     * {@link AutowireCapableBeanFactory#createBean(Class)}
     *
     * @author 阿坤同学
     * @date 2023/12/6 4:52 PM
     */
    public static void createBeanByAutowireCapableBeanFactory() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/special-bean-instantiation-context.xml");
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getBeanFactory();
        UserFactory userFactory = autowireCapableBeanFactory.createBean(DefaultUserFactory.class);
        logger.log(Level.INFO, () -> "AutowireCapableBeanFactory#createBean 创建UserFactory" + userFactory.createUser());
    }

    private static void displayServiceLoad(ServiceLoader<UserFactory> serviceLoader) {
        for (UserFactory userFactory : serviceLoader) {
            logger.log(Level.INFO, () -> "JDK ServiceLoader 方式加载Bean: " + userFactory.createUser());
        }
    }
}
